package com.to8to.autotask.rebate;

import static com.to8to.autotask.util.AutoTaskType.POLLINGFEE_REBATE;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.elasticsearch.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.to8to.autotask.resulthandler.FailHandler;
import com.to8to.autotask.rpc.CallClient;
import com.to8to.autotask.util.DBUtil;
import com.to8to.autotask.util.Utils;
import com.to8to.es.util.LogUtil;
import com.to8to.thrift.crm.itemdb.TItemFP;

/**
 * FeeRebateTask.java
 * 作 者：atom.liu
 * 版 本：v2.0
 * 日 期：2014年11月26日
 * 描 述：自动返款任务(返轮单费)。
 *     自动返款的条件：申请返款+可返状态+有一家公司已返+设置了自动返款，则将自动执行返款。 
 *     2015-01-20:由于在前端页面，在符合条件的情况下，如果装修公司申请返款会自动触发php端的自动返款（装修公司后台），所以这里的自动任务，暂时没用。
 */
class FeeRebateTask implements Runnable
{
    private static final Logger logger = LoggerFactory.getLogger(FeeRebateTask.class);

    /**
     * SQL: 查询出是可返并且申请返款的项目。
     * iscost = 4 ：可返状态
     * chuli = 1 ：装修公司申请返款中
     * fk_zd = 1 ：设置了自动返款
     */
    private static final String APPLY_REBATE_SQL = "select * from to8to_yuyue_apply_fp where iscost = 4 and chuli = 1 and fk_zd = 1";

    /**
     * 查询出已返状态的项目
     * iscost = 2 ： 已返
     */
    private static final String REBEATED_SQL = "select * from to8to_yuyue_apply_fp where yid in (%s) and iscost = 2";

    @Override
    public void run()
    {
        logger.info("自动返款任务开始 ...");

        Connection connect = null;

        try
        {
            connect = DBUtil.getConnection();

            //获得满足条件的项目
            Map<Integer, List<TItemFP>> yidMap = getSatisfyConditionProject(connect);
            if (Utils.isNullOrEmpty(yidMap))
            {
                logger.info("本次没有满足条件的可自动返款的项目");
                return;
            }

            //从申请返款的项目中查询出符合有一家已返的要求
            filteLegalProject(connect, yidMap);
            if (Utils.isNullOrEmpty(yidMap))
            {
                logger.info("本次没有满足条件的可自动返款的项目");
                return;
            }

            if (DBUtil.execTaskCountsAtToday(connect, POLLINGFEE_REBATE) != 0)
                return;

            recordLog(yidMap, connect);
            CallClient.affirmReturnMoney(yidMap);
        }
        catch (Throwable e)
        {
            logger.error("自动返款任务失败！{} \n {}", e, LogUtil.logStackTrace(e));
            if (e instanceof SQLException)
                FailHandler.handler(FeeRebateTask.class);
        }
        finally
        {
            DBUtil.releaseSource(null, null, connect);
        }
    }

    private void recordLog(Map<Integer, List<TItemFP>> map, Connection connect)
    {
        List<String> sqls = Lists.newArrayList();
        sqls.add("本次要调用自动返款的信息：");
        for (Map.Entry<Integer, List<TItemFP>> entry : map.entrySet())
        {
            StringBuilder sb = new StringBuilder();
            sb.append("yid: ").append(entry.getKey()).append("[");
            for (TItemFP info : entry.getValue())
                sb.append("uid:").append(info.getUid()).append(",fid:").append(info.getFid()).append("|");
            sb.append("]");
            sqls.add(sb.toString());
        }
        DBUtil.recordAutoTaskLog(connect, POLLINGFEE_REBATE, sqls, true);
    }

    /**
     * 获得满足条件的项目。
     * @return map<integer,list> key:yid
     */
    private Map<Integer, List<TItemFP>> getSatisfyConditionProject(Connection connect) throws SQLException
    {
        PreparedStatement stat = connect.prepareStatement(APPLY_REBATE_SQL);
        ResultSet result = stat.executeQuery();

        Map<Integer, List<TItemFP>> yidMap = Maps.newHashMap();
        while (result.next())
        {
            int yid = result.getInt("yid");
            List<TItemFP> list = yidMap.get(yid);
            if (null == list)
            {
                list = new ArrayList<TItemFP>();
                yidMap.put(yid, list);
            }

            TItemFP fp = new TItemFP();
            fp.setYid(yid);
            fp.setUid(result.getInt("uid"));
            fp.setFid(result.getInt("fid"));

            list.add(fp);
        }

        DBUtil.releaseSource(result, stat, null);

        return yidMap;
    }

    /**
     * 将不满足条件的项目（不满足已返的公司数大于0）过滤掉 
     */
    private void filteLegalProject(Connection connect, Map<Integer, List<TItemFP>> map) throws SQLException
    {
        logger.info("过滤前，项目yid : " + map.keySet());
        Set<Integer> yidSet = map.keySet();
        String yidStr = Utils.collect2Str(yidSet);
        PreparedStatement stat = connect.prepareStatement(String.format(REBEATED_SQL, yidStr));
        ResultSet result = stat.executeQuery();
        yidSet = new HashSet<Integer>();
        while (result.next())
            yidSet.add(result.getInt("yid"));
        DBUtil.releaseSource(result, stat, null);

        Iterator<Map.Entry<Integer, List<TItemFP>>> it = map.entrySet().iterator();
        while (it.hasNext())
        {
            Map.Entry<Integer, List<TItemFP>> entry = it.next();
            if (!yidSet.contains(entry.getKey()))
                it.remove();
        }
        logger.info("过滤后，项目yid : " + map.keySet().toString());
    }
}
